home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / util / cli / BinHex.lha / Source / BinHex.c
Encoding:
C/C++ Source or Header  |  1999-07-04  |  10.8 KB  |  427 lines

  1. #define NAME     "BinHex"
  2. #define REVISION "19"
  3. #define SDI_ENDCODE
  4. //#define DEBUG
  5.  
  6. /* Programmheader
  7.  
  8.     Name:        BinHex
  9.     Author:        SDI
  10.     Distribution:    PD
  11.     Description:    converts binary into hexadecimal data and reverse
  12.     Compileropts:    -
  13.     Linkeropts:    -l amiga
  14.  
  15.  1.0   03.10.95 : first version
  16.  1.1   15.10.95 : recompiled
  17.  1.2   05.02.96 : recompiled with better includes
  18.  1.3   06.02.96 : MakeHEX instead of MakeBASE
  19.  1.4   10.02.96 : compiled with my own StartUp
  20.  1.5   12.03.96 : added option ONLYDATA, \ Option, english texts
  21.  1.6   04.05.96 : removed error with ReadArgs
  22.  1.7   11.05.96 : option ROWS added
  23.  1.8   12.05.96 : option ASMDATA added
  24.  1.9   11.06.96 : EndCode like in SDI_defines.h
  25.  1.10  16.06.96 : corrected buffer overworking bug
  26.  1.11  06.10.96 : if last char was an \t program hanged - fixed
  27.  1.12  21.11.96 : added option CDATA, same as ASMDATA but for C
  28.  1.13  04.02.97 : added REVERSED option (now MAKEBIN only)
  29.  1.14  09.02.97 : own functions for ASMDATA and CDATA, SIZE parameter
  30.  1.15  08.93.97 : fixed forgotten address problem, compiler error ?
  31.  1.16  18.03.97 : SDI include names changed
  32.  1.17  26.05.97 : fixed problems with c:Ed
  33.  1.18  31.05.97 : SDI_isprint no longer allows 0x7f
  34.  1.19  27.06.99 : added NOASCII
  35. */
  36.  
  37. #include <proto/dos.h>
  38. #include <proto/exec.h>
  39. #include <exec/memory.h>
  40. #include "SDI_defines.h"
  41. #include "SDI_structures.h"
  42. #include "SDI_ASM_STD_protos.h"
  43. #include "SDI_ASM_protos.h"
  44. #include "SDI_protos.h"
  45. #include "SDI_GetLength.c"  /* These files are in SDI_functions.o. Remove */
  46. #include "SDI_FillBuf.c"    /* the lines and build your own makefile.      */
  47. #include "SDI_WriteBuf.c"
  48. #include "SDI_FreeBuf.c"    /* Add also the .lib files to the makefile      */
  49. #include "SDI_GetBuffer.c"  /* to make compilation successful!          */
  50.  
  51. struct SDI_InOut    bin        = {0, 0, 0, 0, 0},
  52.             hex        = {0, 0, 0, 0, 0};
  53. STRPTR            revbuf        = 0;
  54. ULONG            revsize        = 16;
  55. struct RDArgs        *rda        = 0;
  56. ULONG            DosVersion    = 37;        /* forces OS 37!  */
  57.  
  58. #define PARAM "BIN/A,HEX/A,MAKEBIN/S,ONLYDATA/S,ROWS/N,ASMDATA/S,CDATA/S" \
  59.           ",REV=REVERSED/S,SIZE/N,NOTAB/S,NOASCII/S"
  60.  
  61. struct Args {
  62.     STRPTR    bin;
  63.     STRPTR    hex;
  64.     LONG    makebin;
  65.     LONG    onlydata;
  66.     LONG    *rows;
  67.     LONG    asmdata;
  68.     LONG    cdata;
  69.     LONG    reversed;
  70.     LONG    *size;
  71.     LONG    notab;
  72.     LONG    noascii;
  73. };
  74.  
  75. #define NUMPERLINE    (rows<<2)
  76. #define LINESIZE    (rows*(4*(2+1)+1)+8+1+1)
  77. /* rowcount * (4 * (2 numbers + 1 ASCII-character) + 1 space) +
  78.    9 for address + 1 space + 1 return */
  79. #define MAINSIZE    (rows*(4*2+1))
  80. #define ASCIIPOS    (MAINSIZE+8+1)
  81. #define RESTSIZE    (NUMPERLINE+8+1+1)
  82.  
  83. UBYTE GetHEXNum(UBYTE);
  84. STRPTR MakeBin(STRPTR, ULONG, ULONG);
  85. ULONG WriteDataLine(ULONG, ULONG, ULONG);
  86.  
  87. #define MAKECLINE    1
  88. #define MAKEASMLINE    0
  89.  
  90. void main(void)
  91. {
  92.   LONG size = 0;
  93.   struct Args args;
  94.   ULONG h;
  95.   UBYTE rows = 5;
  96.  
  97.   SDI_memset(&args, 0, sizeof(struct Args));
  98.   args.size = &size;
  99.  
  100.   if(!(rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
  101.     End(RETURN_FAIL);
  102.  
  103.   rda->RDA_ExtHelp =
  104. /*
  105.   "Mit dem Programm können binäre Dateien in Hexadezimal dargestellte "
  106.   "Dateien umgewandelt werden. Diese kann man dann mit einem Editor "
  107.   "bearbeitet und wieder in eine Binärdatei umwandeln. "
  108.   "Das Programm liest aus der Hexdatei alle Hex-Zahlen bis zu einem "
  109.   "Tabulator, dann geht es nach dem nächsten Return weiter. Sie müssen "
  110.   "also nicht darauf achten, wieder die genaue Zeilenlänge zu erhalten. "
  111.   "Zwischen Return und Tabulator dürfen jedoch nur die Zeichen 0-9 und A-F "
  112.   "stehen und zwar in einer geraden Anzahl. Das Leerzeichen ist als "
  113.   "Trenner erlaubt. Nach einem \\ wird alles so übernommen, wie gegeben. "
  114.   "Das ist für Texteingaben sehr nützlich.\n";
  115. */
  116.   "Use this program to convert binary data into hexadecimal data. This data "
  117.   "can be edited with a normal text editor. After that it can again become"
  118.   "binary. The program reads in the hexadecimal file all numbers from line "
  119.   "start to next tab stop or return. You do not need to make the linelength "
  120.   "exact as before! Only 0-9 and A-F are allowed in the data part. "
  121.   "Spaces and data after the tab stop are ignored. After a \\ all data is "
  122.   "not converted and taken as given to the binary file (useful for texts).\n";
  123.  
  124.   if(!ReadArgs(PARAM, (LONG *) &args, rda))
  125.     End(RETURN_FAIL);
  126.  
  127.   if(args.rows && *args.rows > 0 && *args.rows < 256)
  128.     rows = (UBYTE) *args.rows;
  129.  
  130.   if((args.makebin && (args.asmdata || args.cdata)) ||
  131.   (args.asmdata && args.cdata))
  132.   {
  133.     PrintFault(ERROR_TOO_MANY_ARGS, 0);
  134.     End(RETURN_FAIL);
  135.   }
  136.  
  137.   if(args.makebin)
  138.   {
  139.     if(
  140.     !(hex.file = Open(args.hex, MODE_OLDFILE)) ||
  141.     !(bin.size = SDI_GetLength(hex.file)))
  142.       End(RETURN_FAIL);
  143.     bin.size = (bin.size >> 2) + 1;
  144.     if(bin.size < NUMPERLINE)
  145.       bin.size = NUMPERLINE;
  146.   }
  147.   else
  148.   {
  149.     if(
  150.     !(bin.file = Open(args.bin, MODE_OLDFILE)) ||
  151.     !(bin.size = SDI_GetLength(bin.file)))
  152.       End(RETURN_FAIL);
  153.   }
  154.  
  155.   if((hex.size = bin.size << 2) > (h = AvailMem(MEMF_LARGEST)))
  156.     hex.size = h;
  157.   if(hex.size < LINESIZE)
  158.     hex.size = LINESIZE;
  159.   if(!SDI_GetBuffer(&hex))
  160.     End(RETURN_FAIL);
  161.   if(args.noascii && args.onlydata)
  162.     args.noascii = 0;
  163.  
  164.   if(args.reversed)
  165.   {
  166.     if(*args.size > 0)
  167.       revsize = *args.size;
  168.  
  169.     if(bin.size < revsize) /* need at least revsize buffer */
  170.       bin.size = revsize;
  171.   }
  172.   else if(*args.size != 2 && *args.size != 4)
  173.     *args.size = 1;                /* set correct size info */
  174.  
  175.   if(bin.size > (h = AvailMem(MEMF_LARGEST)))
  176.     bin.size = (h > revsize ? h : revsize);
  177.  
  178.   if(!SDI_GetBuffer(&bin))
  179.     End(RETURN_FAIL);
  180.  
  181.   if(!(args.makebin ? (bin.file = Open(args.bin, MODE_NEWFILE)) :
  182.   (hex.file = Open(args.hex, MODE_NEWFILE))))
  183.     End(RETURN_FAIL);
  184.  
  185.   if(args.reversed && !(revbuf = (STRPTR) AllocMem(revsize, MEMF_ANY)))
  186.     End(RETURN_FAIL);
  187.  
  188.   if(args.asmdata)
  189.   {
  190.     STRPTR start = "\tDC.B\t";
  191.  
  192.     if(*args.size == 2)
  193.       start[4] = 'W';
  194.     else if(*args.size == 4)
  195.       start[4] = 'L';
  196.  
  197.     SDI_FillBuf(&bin);
  198.     do
  199.     { /* WriteDataLine everytime lets enough space in destination buffer */
  200.       CopyMem(start, hex.pos, 6);
  201.       hex.pos += 6;
  202.     } while(WriteDataLine(*args.size, rows<<2, MAKEASMLINE));
  203.     SDI_WriteBuf(&hex, 0);
  204.   }
  205.   else if(args.cdata)
  206.   {
  207.     SDI_FillBuf(&bin);
  208.     switch(*args.size)
  209.     {
  210.     case 1: CopyMem("UBYTE bin_data[] = {\n", hex.pos, 21); break;
  211.     case 2: CopyMem("UWORD bin_data[] = {\n", hex.pos, 21); break;
  212.     case 4: CopyMem("ULONG bin_data[] = {\n", hex.pos, 21); break;
  213.     };
  214.     hex.pos += 21;
  215.  
  216.     do
  217.     {
  218.       *(hex.pos++) = ' '; *(hex.pos++) = ' ';
  219.     } while(WriteDataLine(*args.size, rows<<2, MAKECLINE));
  220.     *(hex.pos++) = '}';
  221.     *(hex.pos++) = ';';
  222.     *(hex.pos++) = '\n';
  223.     SDI_WriteBuf(&hex, 0);
  224.   }
  225.   else if(args.makebin)
  226.   {
  227.     SDI_FillBuf(&hex);
  228.     if(!args.reversed)
  229.     {
  230.       while(!(bin.pos = MakeBin(bin.pos, bin.size, args.notab)))
  231.       {
  232.         bin.pos = bin.buf + bin.size;
  233.         SDI_WriteBuf(&bin, 0);
  234.       }
  235.     }
  236.     else
  237.     {
  238.       STRPTR bufptr;
  239.       while(!(bufptr = MakeBin(revbuf, revsize, args.notab)))
  240.       {
  241.           bufptr = revbuf + revsize;
  242.         if(bin.buf+bin.size-bin.pos < revsize)
  243.           SDI_WriteBuf(&bin, 0);
  244.     while(bufptr != revbuf)
  245.       *(bin.pos++) = *(--bufptr);
  246.       }
  247.       if(bin.buf+bin.size-bin.pos < bufptr-revbuf)
  248.         SDI_WriteBuf(&bin, 0);
  249.       while(bufptr != revbuf)
  250.     *(bin.pos++) = *(--bufptr);
  251.     }
  252.     SDI_WriteBuf(&bin, 0);
  253.   }
  254.   else
  255.   {
  256.     ULONG address = 0;
  257.  
  258.     SDI_FillBuf(&bin);
  259.     while(bin.count && !CTRL_C)
  260.     {
  261.       STRPTR strptr;
  262.  
  263.       strptr = hex.pos + ASCIIPOS;
  264.  
  265.       for(h = 0; h < NUMPERLINE; ++h, ++bin.pos)
  266.       {
  267.         if(bin.pos < bin.buf + bin.count)
  268.         {
  269.       SDI_MakeHEX(hex.pos, 2, *bin.pos);
  270.       hex.pos += 2;
  271.           if(!args.onlydata && !args.noascii)
  272.             *(strptr++) = SDI_isprint(*bin.pos) ? *bin.pos : '.';
  273.     /* C:Ed cannot handle 0x7F */
  274.         }
  275.     else if(args.onlydata || args.noascii)
  276.       break;
  277.         else
  278.         {
  279.           *(hex.pos++) = ' '; *(hex.pos++) = ' ';
  280.           *(strptr++) = ' ';
  281.         }
  282.         if(!((h+1 & 3) || args.onlydata))
  283.           *(hex.pos++) = ' ';
  284.       }
  285.       if(!args.onlydata && !args.noascii)
  286.       {
  287.         *hex.pos = '$';
  288.         SDI_MakeHEX(hex.pos+1, 7, address);
  289.         *(hex.pos-1) = '\t'; *(hex.pos+8) = ' ';  *strptr = '\n';
  290.         hex.pos += RESTSIZE;
  291.       }
  292.       else if(args.noascii)
  293.     *(hex.pos-1) = '\n';
  294.       else
  295.     *(hex.pos++) = '\n';
  296.       address += NUMPERLINE;
  297.       if(bin.pos >= bin.buf + bin.count - NUMPERLINE)
  298.         SDI_FillBuf(&bin);
  299.       if(hex.pos >= hex.buf + hex.size - LINESIZE)
  300.         SDI_WriteBuf(&hex, 0);
  301.     }
  302.     SDI_WriteBuf(&hex, 0);
  303.   }
  304.  
  305.   End(RETURN_OK);
  306. }
  307.  
  308. UBYTE GetHEXNum(UBYTE h)
  309. {
  310.   if(h > 47 && h < 58)
  311.     return (UBYTE) (h - '0');
  312.   else if(h > 64 && h < 71)
  313.     return (UBYTE) (h - 'A' + 10);
  314.   else if(h > 96 && h < 103)
  315.     return (UBYTE) (h - 'a' + 10);
  316.   return 0;
  317. }
  318.  
  319. STRPTR MakeBin(STRPTR buf, ULONG size, ULONG notab)
  320. {
  321.   static ULONG line = 1, row = 1;
  322.   static UBYTE realmode = 0;
  323.  
  324.   while(hex.count && !CTRL_C)
  325.   {
  326.     if(*hex.pos == '\t' || (notab && *hex.pos == '$'))
  327.     {
  328.       while(hex.count && *hex.pos != '\n')
  329.       {
  330.         ++hex.pos;
  331.         if(hex.pos >= hex.buf + hex.count - 2)
  332.           SDI_FillBuf(&hex);
  333.       }
  334.     }
  335.     else if(*hex.pos == '\n')
  336.     {
  337.       ++line; row = 1; ++hex.pos; realmode = 0;
  338.     }
  339.     else if(!realmode && *hex.pos == ' ')
  340.     {
  341.       ++hex.pos; ++row;
  342.     }
  343.     else if(*hex.pos == '\\')
  344.     {
  345.       realmode = 1; ++hex.pos;
  346.     }
  347.     else
  348.     {
  349.       if(realmode)
  350.       {
  351.         *(buf++) = *(hex.pos++); ++row; --size;
  352.       }
  353.       else
  354.       {
  355.         if(!SDI_isxdigit(*hex.pos) || !SDI_isxdigit(*(hex.pos+1)))
  356.         {
  357.       Printf("line %ld, row %ld : ", line, row);
  358.       SetIoErr(ERROR_SEEK_ERROR);
  359.           End(RETURN_FAIL);
  360.         }
  361.         *buf = GetHEXNum(*(hex.pos++)) << 4;
  362.         *(buf++) += GetHEXNum(*(hex.pos++));
  363.         --size;
  364.         row+=2;
  365.       }
  366.     }
  367.     if(hex.pos >= hex.buf + hex.count - 2)
  368.       SDI_FillBuf(&hex);
  369.     if(!size)
  370.       return 0;
  371.   }
  372.   return buf;
  373. }
  374.  
  375. ULONG WriteDataLine(ULONG size, ULONG bytes, ULONG type)
  376. {
  377.   ULONG pos = size;
  378.   while(bin.count && !CTRL_C)
  379.   {
  380.     if(hex.pos >= hex.buf + hex.size - 20)
  381.       SDI_WriteBuf(&hex,0);
  382.     if(pos == size)
  383.     {
  384.       pos = 0;
  385.       if(!type)
  386.         *(hex.pos++) = '$';
  387.       else
  388.       {
  389.         *(hex.pos++) = '0'; *(hex.pos++) = 'x';
  390.       }         
  391.     }
  392.     SDI_MakeHEX(hex.pos, 2, *(bin.pos++)); hex.pos += 2;
  393.     --bytes;
  394.     if((++pos == size) && (type || bytes))
  395.       *(hex.pos++) = ',';
  396.     if(bin.pos >= bin.buf + bin.count)
  397.       SDI_FillBuf(&bin);
  398.     if(!bytes && bin.count)
  399.     {
  400.       *(hex.pos++) = '\n'; return 1;
  401.     }
  402.   }
  403.  
  404.   while(pos != size)
  405.   {
  406.     ++pos; *(hex.pos++) = '0'; *(hex.pos++) = '0';
  407.   }
  408.  
  409.   *(hex.pos++) = '\n';
  410.  
  411.   return 0;
  412. }
  413.  
  414. void end(void)
  415. {
  416.   if(bin.file)        Close(bin.file);
  417.   if(hex.file)        Close(hex.file);
  418.   SDI_FreeBuf(&bin);
  419.   SDI_FreeBuf(&hex);
  420.   if(rda)
  421.   {
  422.     FreeArgs(rda);
  423.     FreeDosObject(DOS_RDARGS, rda);
  424.   }
  425. }
  426.  
  427.